﻿using AuthTemplate.DTO.Module;
using AuthTemplate.DTO.User;
using AuthTemplate.Entity;
using AuthTemplate.Entity.Common;
using AuthTemplate.Infrastructure;
using AuthTemplate.Infrastructure.AutoMapper;
using AuthTemplate.Repository.Interface;
using AuthTemplate.Repository.Interface.IEntityRepository;
using AuthTemplate.Repository.Repositories;
using AuthTemplate.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AuthTemplate.Service
{
    public class ModuleService : BaseService, IModuleService
    {
        private readonly IModuleRepository moduleRepository;
        private readonly IModuleElementRepository moduleElementRepository;
        private readonly IRelevanceRepository relevanceRepository;
        private readonly IUnitOfWork unitOfWork;
        public ModuleService(IModuleRepository moduleRepository,
            IModuleElementRepository moduleElementRepository,
            IRelevanceRepository relevanceRepository,
            IUnitOfWork unitOfWork)
        {
            this.moduleRepository = moduleRepository;
            this.moduleElementRepository = moduleElementRepository;
            this.relevanceRepository = relevanceRepository;
            this.unitOfWork = unitOfWork;
        }

        public List<ModuleDto> LoadForUser(string userId)
        {
            var roleIDs = relevanceRepository.FindBy(s => (s.FirstId == userId && s.Status==1 && s.KeyType == RelevanceType.USERROLE))
                                             .Select(s=>s.SecondId);
            var moduleIDs = relevanceRepository.FindBy(s =>
                                                        (s.KeyType == RelevanceType.ROLEMODULE && s.Status ==1 && roleIDs.Contains(s.FirstId)))
                                                    .Select(s => s.SecondId);
            var modules = moduleRepository.FindBy(s => moduleIDs.Contains(s.Id) && s.Status==1);

            return GetModuleDtos(modules.ToList());
        }

        public List<ModuleDto> LoadForRole(List<string> roleIDs)
        {
            var moduleIDs = relevanceRepository.FindBy(s =>
                                                        (s.KeyType == RelevanceType.ROLEMODULE && s.Status==1 && roleIDs.Contains(s.FirstId)))
                                                    .Select(s => s.SecondId);
            var modules = moduleRepository.FindBy(s => moduleIDs.Contains(s.Id) && s.Status ==1);

            return GetModuleDtos(modules.ToList());
        }


        public List<Module> GetModulePage(int page, int limit ,out int count)
        {
            count = moduleRepository.FindBy(s=>s.Status==1).Count();
            var modules = moduleRepository.FindBy(s => s.Status == 1).OrderBy(s=>s.CascadeId).Skip((page-1)*limit).Take(limit);
            return modules.ToList();
        }

        public void EditModule(EditModuleInput input)
        {
            Module module = input.Map<Module>();
            List<string> paraList = new List<string>()
            {
                "CascadeId","Name","Url","IsRoot","IconName",
                "Status","ParentName","SortNo","ParentId"
            };
            moduleRepository.Edit(module, paraList.ToArray());
            unitOfWork.Commit();
        }

        public void AddModule(AddModuleInput input)
        {
            Module module = input.Map<Module>();
            moduleRepository.Add(module);
            unitOfWork.Commit();
        }

        public void DeleteModule(string id)
        {
            Module module = new Module();
            module.Id = id;
            moduleRepository.Delete(module);
            unitOfWork.Commit();
        }

        #region private 方法

        private List<ModuleDto> GetModuleDtos(List<Module> modules)
        {
            List<ModuleDto> moduleDtos = new List<ModuleDto>();
            foreach (var item in modules.FindAll(s => s.IsRoot == true).OrderBy(s => s.CascadeId))
            {
                ModuleDto dto = new ModuleDto();
                dto.id = item.Id;
                dto.title = item.Name;
                dto.icon = item.IconName;
                dto.href = item.Url;
                dto.spread = false;
                dto.children = GetChild(modules, item.Id);

                moduleDtos.Add(dto);
            }
            return moduleDtos;
        }
        private List<ModuleDto> GetChild(List<Module> modules, string id)
        {
            List<ModuleDto> moduleDtos = new List<ModuleDto>();
            foreach (var item in modules.FindAll(s => s.IsRoot == false && s.ParentId == id).OrderBy(s => s.CascadeId))
            {
                ModuleDto dto = new ModuleDto();
                dto.id = item.Id;
                dto.title = item.Name;
                dto.icon = item.IconName;
                dto.href = item.Url;
                dto.spread = false;
                dto.children = GetChild(modules, item.Id);

                moduleDtos.Add(dto);
            }
            return moduleDtos;

        }

        #endregion

    }

    public interface IModuleService
    {
        List<ModuleDto> LoadForUser(string userId);

        List<ModuleDto> LoadForRole(List<string> roleIDs);

        List<Module> GetModulePage(int page, int limit ,out int count);
        void EditModule(EditModuleInput input);
        void AddModule(AddModuleInput input);
        void DeleteModule(string id);
    }
}
